#ifndef _SCUDB_TRANSACTION_H_
#define _SCUDB_TRANSACTION_H_

#include "sd_global.h"
#include "sd_thread.h"
#include "sd_log.h"
#include "sd_blist.h"
#include "sd_synchashtable.h"
#include "sd_oplog.h"


/* Definition of transaction */
typedef struct sd_Transaction
{
	bool isUsed;
	uint32 tid;
	sd_Hashtable* lockTable; /* Store the locked record's id in this transaction */
	sd_OpLog opLog; /* operating log for rollback the transaction */

}sd_Transaction;

typedef struct sd_TxnLockItem
{
	bool isRLocked;
	bool isWLocked;
}sd_TxnLockItem;

typedef struct sd_RecordLockItem
{
	int* locktimes;
	sd_RWLock lock;
}sd_RecordLockItem;

typedef struct sd_TxnManager
{
	sd_SpinLock  txnPoolLock;
	sd_SyncHashtable* lockTable;
	uint32 txnHashsize;
	uint32 txnHashNodeSize;
	uint32 maxNumActiveTxns;
	uint32 freeTxnStartIndex;
	struct timespec txnLockTimeout;
	sd_Transaction activeTxns[1];
}sd_TxnManager;


typedef struct sd_TxnState
{
	sd_TxnManager* txnManager;
	uint32 tid;
	bool bNewCreated;
}sd_TxnState;

sd_Ret sd_TxnManagerCreate(sd_TxnManager** txnman, size_t maxNumActive, size_t logListNodeSize, size_t lockHashsize, size_t tableNodeSize,
						    struct timespec txnLockTimeout);
sd_Ret sd_TxnManagerFree(sd_TxnManager* txnman);
sd_Ret sd_TxnManagerBeginTransaction(sd_TxnManager* txnman, sd_TxnState* txnState);
sd_Ret sd_TxnManagerCommitTransaction(sd_TxnState* txnState);
sd_Ret sd_TxnManagerAbortTransaction(sd_TxnState* txnState);


sd_Ret sd_TxnRLock(sd_TxnState* txnState, sd_uid rid);
sd_Ret sd_TxnWLock(sd_TxnState* txnState, sd_uid rid);
sd_Ret sd_TxnUnlockAll(sd_TxnState* txnState);

#define sd_TxnGetOpLog(txnState) (&(txnState)->txnManager->activeTxns[(txnState)->tid].opLog)
#define sd_TxnAddLog(txnState,logItem) sd_OpLogPushback(sd_TxnGetOpLog(txnState), logItem)
sd_Ret sd_TxnRollback(sd_TxnState* txnState);

#endif
